/*
 * Copyright (C) 2012 The Yuike Mobile Develop Common Framework Project
 *
 * YkAnimationStep.m
 * 
 * @brief: 		动画播放的类
 * 
 * @author   	wanggang
 * @date     	2012-1-5
 */

#import "YkAnimationStep.h"
#import "header.h"

//@interface YkAnimationStep()
//
//@end

@implementation YkAnimationStep

@synthesize delay;
@synthesize duration;
@synthesize step;
@synthesize options;
@synthesize consumableSteps;


- (void)dealloc
{
    YRelease(step);    
    YRelease(consumableSteps);
    
    [super dealloc];
}
#pragma mark overrides


#pragma mark construction

+ (id) after:(NSTimeInterval)delay animate:(AnimationStep)step {
	return [self after:delay for:0.0f options:0 animate:step];
}

+ (id) for:(NSTimeInterval)duration animate:(AnimationStep)step {
    return [self after:0.0 for:duration options:0 animate:step];
}

+ (id) for:(NSTimeInterval)duration options:(UIViewAnimationOptions)theOptions animate:(AnimationStep)step 
{
    return [self after:0.0 for:duration options:theOptions animate:step];
}

+ (id) after:(NSTimeInterval)delay for:(NSTimeInterval)duration animate:(AnimationStep)step {
	return [self after:delay for:duration options:0 animate:step];
}

+ (id) after:(NSTimeInterval)theDelay
for:(NSTimeInterval)theDuration
options:(UIViewAnimationOptions)theOptions
animate:(AnimationStep)theStep {
	
	YkAnimationStep* instance = [[[self alloc] init] autorelease];
	if (instance) {
		instance.delay = theDelay;
		instance.duration = theDuration;
		instance.options = theOptions;
		instance.step = theStep;
	}
	return instance;
}

#pragma mark action

// http://stackoverflow.com/questions/4007023/blocks-instead-of-performselectorwithobjectafterdelay
+ (void) runBlock:(AnimationStep)block afterDelay:(NSTimeInterval)delay {
	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay), dispatch_get_current_queue(), block);
}

- (NSArray*) animationStepArray {
	// subclasses must override this
	return [NSArray arrayWithObject:self];
}

- (void) runAnimated:(BOOL)animated {
	if (!self.consumableSteps) 
    {
        self.consumableSteps = [NSMutableArray arrayWithArray:[self animationStepArray]];
	}
	if (![self.consumableSteps count]) { 
		self.consumableSteps = nil;
		return; 
	}
	AnimationStep completionStep = ^{
		[self.consumableSteps removeLastObject];
		[self runAnimated:animated]; 
	};
	YkAnimationStep* currentStep = [self.consumableSteps lastObject];

	if (animated) {
		[UIView animateWithDuration:currentStep.duration
							  delay:currentStep.delay
							options:currentStep.options
						 animations:currentStep.step
						 completion:^(BOOL finished) {
							 if (finished) {
								 completionStep();
							 }
						 }];
	} else {
		void (^execution)(void) = ^{
			currentStep.step();
			completionStep();
		};
    
        execution();		
	}
}

- (void) runAnimation {
    @autoreleasepool {
        [self runAnimated:YES];
    }	
}

#pragma mark - pretty-print

- (NSString*) description {
	NSMutableString* result = [[NSMutableString alloc] initWithCapacity:100];
	[result appendString:@"\n["];
	if (self.delay > 0.0) {
		[result appendFormat:@"after:%.1f ", self.delay];
	}
	if (self.duration > 0.0) {
		[result appendFormat:@"for:%.1f ", self.duration];
	}
	if (self.options > 0) {
		[result appendFormat:@"options:%d ", self.options];
	}
	[result appendFormat:@"animate:%@", self.step];
	[result appendString:@"]"];
	return [result autorelease];
}
@end
